package com.example.blog.util;
import cn.hutool.core.lang.UUID;
import com.example.entity.Resources;
import com.example.mapper.ResourcesMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Objects;

/**
 * @Classname FileUtil
 * @Description TODO 文件操作工具类（单机存放的资源）
 * @Version 1.0.0
 * @Date 2023/2/2 19:54
 * @Created by wlh12
 */
@Component
@Slf4j
public class FileUtil {

    public static final String[] imgs = {
            "jpg",
            "png",
    };

    // 从配置中获取文件保存路径
    @Value("${imgPath}")
    public String imgPath;

    @Value("${mp4Path}")
    public String mp4Path;

    @Resource
    private ResourcesMapper resourcesMapper;

    @Autowired
    private NonStaticResourceHttpRequestHandler nonStaticResourceHttpRequestHandler;
    // 前端实现文件上传，保存到服务器
    public String upload(MultipartFile file){
        if (Objects.isNull(file)){
            throw new RuntimeException("文件不能为空");
        }
        // 1、获取上传的文件的名称
        String filename = file.getOriginalFilename();
        // 2、保存到本地
        // 2.1 获取文件的后缀，保证上传文件类型正确
        String suffix = filename.substring(filename.lastIndexOf("."));
        // 2.2 设置文件的唯一名称
        String newFileName = UUID.randomUUID().toString()+suffix;
        // 2.3 判断保存路径的文件是否存在（不存在则创建）
        File saveFile = new File(imgPath);
        if (!saveFile.exists()){
            saveFile.mkdirs();
        }
        try {
            // 2.4 保存到指定路径
            file.transferTo(new File(imgPath+"/"+newFileName));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 3、返回文件的名称
        return newFileName;
    }

    /**
     * 只能上传图片
     * @param file
     * @return
     */
    public String uploadImage(MultipartFile file){
        if (Objects.isNull(file)){
            throw new RuntimeException("文件不能为空");
        }
        // 1、获取上传的文件的名称
        String filename = file.getOriginalFilename();
        // 2、保存到本地
        // 2.1 获取文件的后缀，保证上传文件类型正确
        String suffix = filename.substring(filename.lastIndexOf("."));
        boolean allMatch = Arrays.stream(imgs).anyMatch(i -> i.equals(suffix));
        if (!allMatch){
            throw new RuntimeException("图片类型只能为jpg、png格式");
        }
        // 2.2 设置文件的唯一名称
        String newFileName = UUID.randomUUID().toString()+suffix;
        // 2.3 判断保存路径的文件是否存在（不存在则创建）
        File saveFile = new File(imgPath);
        if (!saveFile.exists()){
            saveFile.mkdirs();
        }
        try {
            // 2.4 保存到指定路径
            file.transferTo(new File(imgPath+"/"+newFileName));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 3、返回文件的名称
        return newFileName;
    }
    /**
     * 图片文件展示到页面
     * @param fileName
     * @param response
     */
    public void downloadAndShow(String fileName, HttpServletResponse response) {
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        try {
            // 文件输入流对象，用于从磁盘读取文件
            FileInputStream inputStream = new FileInputStream(new File(imgPath+fileName));
            // 写到页面
            ServletOutputStream outputStream = response.getOutputStream();
            // 管道流
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = inputStream.read(bytes))!=-1) {
                // 到输出流
                outputStream.write(bytes,0,len);
                // 刷新并强制输出到页面
                outputStream.flush();
            }
            inputStream.close();
            outputStream.close();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 将文件下载到用户客户端
     * @param fileName
     * @param response
     */
    public void download(String fileName ,HttpServletResponse response){
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        try {
            // 文件输入流对象，用于从磁盘读取文件
            FileInputStream inputStream = new FileInputStream(new File(imgPath+fileName));
            // 写到页面
            ServletOutputStream outputStream = response.getOutputStream();
            // 设置为二进制流数据（如常见的文件下载）
            response.setContentType("application/octet-stream");
            // 管道流
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = inputStream.read(bytes))!=-1) {
                // 到输出流
                outputStream.write(bytes,0,len);
                // 刷新并强制输出到页面
                outputStream.flush();
            }
            inputStream.close();
            outputStream.close();
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    // 返回视频流
    public void play(Integer id, HttpServletRequest request, HttpServletResponse response){
        Resources resources = resourcesMapper.selectById(id);
        Path filePath = Paths.get(mp4Path+resources.getContentUrl());
        try {
            if (Files.exists(filePath)) {
                String mimeType = Files.probeContentType(filePath);
                if (!StringUtils.isEmpty(mimeType)) {
                    response.setContentType(mimeType);
                }
                request.setAttribute(NonStaticResourceHttpRequestHandler.filepath, filePath);
                nonStaticResourceHttpRequestHandler.handleRequest(request, response);
            } else {
                response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }
}
